#pragma once 
#include "Channel.hpp"
#include "Task.hpp"
#include <sys/wait.h>

void Worker(){
    int cmd = 0;
    cout << "子进程" << getpid()<< "开始等待" << endl;
    while(true){
        int ret = ::read(0,&cmd,sizeof(cmd));
        if (ret > 0){
            tm.Execute(cmd);
        } 
        else if (ret==0){
            cout << "父进程退出" << endl;
            break;
        }
        else {
            cout << "子进程获取任务失败" << endl;
           return;
        }
    }
}

class ProcessPool
{
    using func = function<void()>;
public:
    //给出创建多少个进程
    ProcessPool(int num)
        :_processnum(num)
    {
        srand(time(nullptr));
        
    }
    void Init(){
        for (int i = 0; i < _processnum; i++){
            int fds[2] = { 0 };
            if (pipe(fds) < 0){
                perror("创建管道失败");
                return ;
            }
            pid_t id = fork();
            if (id > 0){
                //父进程 (写)
                ::close(fds[0]);
                cout << "父进程读端: " << fds[1] << endl;
                _channels.emplace_back(fds[1],id);
            }
            else  {
                //子进程(读端)
                ::close(fds[1]);
                ::dup2(fds[0],0); //都从标准输入读取
                cout << "子进程读端: " << fds[0] << endl;
                Worker(); //子进程干什么事情这个只是接受而已, 用户需要自己封装
                cout << "子进程" << getpid() << "退出" << endl;
                ::close(fds[0]);
                exit(0);
            }
        }
    }
    void Run(){
        int total = 5;
        int who = 0;
        //不断的发送任务
        while(total--){
            int tasknum = tm.Select();
            cout << "子进程:-" << _channels[who].Name() << "去执行" << tasknum << "号任务" << endl;
            who = (who + 1) % _channels.size();
            _channels[who].Send(tasknum);
            sleep(1);
        }
    }
    void Wait(){
        for (auto& c : _channels){
            c.Close();
        }
        for (auto& x : _channels){
            int status = 0;
            pid_t child = waitpid(x.Who(),&status,0);
            if (child > 0){
                printf("wait %d success, status:%d, errorcode:%d\n",child,(status>>8)&0xFF,status&0x7F);
            }
        }
        //倒序删除法
        // for (int i = _channels.size()-1; i >= 0; i--){
        //     _channels[i].Close();
        // }
        // for (int i = _channels.size()-1; i >= 0; i--){
        //     int status = 0;
        //     pid_t child = waitpid(_channels[i].Who(),&status,0);
        //     if (child > 0){
        //         printf("wait %d success, status:%d, errorcode:%d\n",child,(status>>8)&0xFF,status&0x7F);
        //     }
        // }
    }
private:
    int _processnum;
    vector<Channel> _channels;
};